# coding=utf-8
import hashlib
import hmac
import uuid
import base64

from Crypto.Cipher import AES
from pyDes import *
from settings import CHUANG_LAN_FLASH_APPS
import binascii
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

from social.account import logger
from social.exceptions import TelecomUnsupportedException, FlashLoginException, PhoneIsBlackException
from social.utils.ip_utils import reverse_ip_location
from social.city import *
from django.core.cache import cache


def default_user_name(phone_code: int, phone: str) -> str:
    if not phone:
        return None
    return f"{phone_code}_{phone}"


def flash_login(client_data: dict):
    telecom = client_data['telecom']
    app_id = client_data['appId']

    url_path = {"CUCC": "mobile-query-u",
                "CTCC": "mobile-query-t",
                "CMCC": "mobile-query-m"}
    path = url_path[telecom]
    if not path:
        raise TelecomUnsupportedException()

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0'
    }

    multipart_encoder = MultipartEncoder(
        fields=client_data,
        boundary=uuid.uuid4()
    )

    headers['Content-Type'] = multipart_encoder.content_type

    app_key = CHUANG_LAN_FLASH_APPS[app_id]

    url = "https://api.253.com/open/flashsdk/" + path
    r = requests.post(url, data=multipart_encoder, headers=headers)
    print(r.text)
    if r.json()['code'] == '200000':
        return decrypt(r.json()['data']['mobileName'].encode(), app_key.encode()).decode()

    raise FlashLoginException()


def flash_login_v2(token: str, app_id: str):
    cache_key = hashlib.md5((token + "_" + app_id).encode('utf-8')).hexdigest()
    cached_phone = cache.get(cache_key)
    if cached_phone:
        return str(cached_phone)

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0'
    }
    app_key = CHUANG_LAN_FLASH_APPS[app_id]

    multipart_encoder = MultipartEncoder(
        fields={
            "appId": app_id,
            "token": token,
            "sign": hmac.new(bytes(app_key, "latin-1"),
                             msg=bytes(f"appId{app_id}token{token}", "latin-1"),
                             digestmod=hashlib.sha256).hexdigest().upper()
        },
        boundary=uuid.uuid4()
    )

    headers['Content-Type'] = multipart_encoder.content_type

    url = "https://api.253.com/open/flashsdk/mobile-query"
    r = requests.post(url, data=multipart_encoder, headers=headers)
    print(r.text)

    if r.json()['code'] == '200000':
        phone = decrpt_phone_v2(r.json()['data']['mobileName'], app_key)
        cache.set(cache_key, phone, 60 * 5)
        return phone

    raise FlashLoginException()


def decrypt(data, KEY):
    IV = chr(1) + chr(2) + chr(3) + chr(4) + chr(5) + chr(6) + chr(7) + chr(8)
    k = des(KEY, CBC, IV, pad=None, padmode=PAD_PKCS5)
    return k.decrypt(base64.decodebytes(data))


def decrpt_phone_v2(data, appKey):
    def unpad(s):
        return s[0:-ord(s[-1:])]

    print("decrpt_phone_v2:", data, appKey)
    md5 = hashlib.md5()
    md5.update(appKey.encode())
    keyHash = md5.hexdigest()
    cipher = AES.new(keyHash[:16].encode(), AES.MODE_CBC, keyHash[-16:].encode())
    msg = cipher.decrypt(binascii.a2b_hex(data))
    res = unpad(msg).decode()
    print(res)
    return res


def valid_zip_code(ip):
    try:
        ip_result = reverse_ip_location(ip)
        if not ip_result.get('zipcode'):
            return 0
        ip_zip_code = int(ip_result['zipcode'])
        base_area = all_places.get(ip_zip_code, None)
        if base_area:
            if isinstance(base_area, Area) and base_area.city:
                return base_area.city.id
            elif isinstance(base_area, City):
                return base_area.id
            elif isinstance(base_area, Province):
                if base_area.is_municipality:
                    return base_area.id
    except Exception as e:
        logger.error("Reverse Ip Exception:" + str(e))
    return 0


def check_phone_is_black(phone, ip='', raise_exception=False):
    return False
